// capsensetriform.cpp

#include "capsensetriform.h"

#include "CapSenseTri/capsenseinterface.h"
#include "Thread/imagesavemanager.h"
#include "qdebug.h"
#include "qobjectdefs.h"
#include "ui_capsensetriform.h"

#include <QFile>
#include <QFormLayout>
#include <QGraphicsDropShadowEffect>
#include <QLabel>
#include <QTextStream>
#include <QGridLayout>
#include <QDateTime>
#include <QSettings>
#include <QTextCodec>
#include <QDir>
#include <QMessageBox>
#include <Alg/ImageConvert.h>
#include <Alg/weldingalgorithmmanager.h>
#include <Form/algorithmparammanager.h>
#include <Common/SysEnv.h>
#include <Common/cvqt_text.hpp>


CapSenseTriForm::CapSenseTriForm(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::CapSenseTriForm)
{
    ui->setupUi(this);
    ui->Bt_start->setEnabled(false);
    // 初始化运行时间计时器
    m_runtimeTimer = new QTimer(this);
    m_runtimeSeconds = 0;
    m_runtimeString = "00000:00:00";
    connect(m_runtimeTimer, &QTimer::timeout, this, [this]() {
        m_runtimeSeconds++;
        updateRuntimeDisplay();
    });

    m_imageSaveManager = new ImageSaveManager();
    m_imageSaveManager->initialize();

    readConfig();
    initWindow();
    initCameras();

    qRegisterMetaType<cv::Mat>("cv::Mat");
    // 设置结果回调
    Alg::WeldingAlgorithmManager::instance().setResultCallback(
        [this](const WeldingResult& results) {
            // 使用Qt的元对象系统确保在UI线程执行
            QMetaObject::invokeMethod(this, "onAlgorithmResultReady",
                                      Qt::QueuedConnection,
                                      Q_ARG(WeldingResult,results));
        });
    // 连接参数变更信号
    connect(AlgorithmParamManager::instance(), &AlgorithmParamManager::algParamChanged,
            this, &CapSenseTriForm::onAlgParamChanged);

    // 初始化本地参数
    m_currentAlgParam = AlgorithmParamManager::instance()->getAlgParam();

    // 从 SysEnv 加载自启动设置
    ui->cb_autoStart->setChecked(SysEnv::instance().getAutoStart());

    m_sql.init("MainForm_db");
}

CapSenseTriForm::~CapSenseTriForm()
{
    releaseAllCameras();
    delete ui;
}

void CapSenseTriForm::handleFrame(CFrameInfo frameInfo)
{

    int currentId = getCameraID(frameInfo.cameraKey);
    if (currentId <= 0) {
        qWarning() << "Invalid camera ID:" << frameInfo.cameraKey;
        return;
    }

    auto& targetList = (currentId == 1) ? m_vListC1 : m_vListC2;

    // 转换为Mat
    cv::Mat frameMat;
    try {
        switch(frameInfo.m_ePixelType) {
        case gvspPixelRGB8:
            frameMat = cv::Mat(frameInfo.m_nHeight,
                               frameInfo.m_nWidth,
                               CV_8UC3,
                               frameInfo.m_pImageBuf.get()).clone();
            cv::cvtColor(frameMat, frameMat, cv::COLOR_RGB2BGR);
            break;
        case gvspPixelMono8:
        {
            cv::Mat gray = cv::Mat(
                               frameInfo.m_nHeight,
                               frameInfo.m_nWidth,
                               CV_8UC1,
                               frameInfo.m_pImageBuf.get()
                               ).clone();
            cv::cvtColor(gray, frameMat, cv::COLOR_GRAY2BGR);
            break;
        }
        default:
            qWarning() << "Unsupported format:" << frameInfo.m_ePixelType;
            return;
        }
    } catch (const cv::Exception& e) {
        qWarning() << "OpenCV exception:" << e.what();
        return;
    }

    m_imageSaveManager->saveRawImage(currentId-1, frameMat, m_vTriggerIndexs[currentId-1], m_vImgIndexs[currentId-1]);

    // 增加原始图像索引
    m_vImgIndexs[currentId-1]++;
    // 添加到列表
    targetList.push_back(std::move(frameMat));

    // 当收集到4张图像时处理
    if (targetList.size() == 4) {

        std::vector<cv::Mat> imagesCopy = targetList;
        Alg::CameraFunc(imagesCopy, currentId-1);

        m_processStartTime = QDateTime::currentMSecsSinceEpoch();
        targetList.clear();
    }
}

void CapSenseTriForm::onAlgorithmResultReady(const WeldingResult& result)
{
    if (result.dst.empty())
    {
        qWarning() << "CapSenseTriForm: received empty cv::Mat";
        return;
    }

    int cameraId = result.id+1;
    CapSenseInterface face;
    if(m_isRun){
        QStringList lines;
        std::vector<LineStyle> styles;
        QString strNGReults;

        // 根据检测结果设置颜色
        QColor rowColor = Qt::green; // 默认颜色
        QColor specificColumnColor = Qt::red;
        int errorColumn = -1; // 记录导致错误的特定列

        switch (result.NO_HX_NGReults)
        {
        case OK:
            strNGReults = tr("OK");
            lines << strNGReults;
            styles.push_back(LineStyle{40, Qt::green, "Consolas", QFont::Bold});
            specificColumnColor = Qt::black;
            break;
        case HXAREA_Err:
            strNGReults = tr("HXAREA_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.HX_Area, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 3; // Area列

            strNGReults = tr("LT_SUM:");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.LT_SumArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});

            strNGReults = tr("LT_MAX:");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.LT_MaxArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});

            strNGReults = tr("HD_SUM:");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.HD_SumArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});

            strNGReults = tr("HD_MAX:");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.HD_MaxArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            break;
        case HXSIZE_H_Err:
            strNGReults = tr("HXSIZE_H_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.hxResult[0].hx_height, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 2; // Height列
            break;
        case HXSIZE_W_Err:
            strNGReults = tr("HXSIZE_W_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.hxResult[0].hx_weight, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 1; // Weight列
            break;
        case YJ_Err:
            strNGReults = tr("YJ_Err");
            lines << strNGReults;
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 10; // 结果列
            break;
        case HXPY_Err:
            strNGReults = tr("HXPY_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.hxResult[0].center_pianyi, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 5; // Offset列
            break;
        case TBDIS_Err:
            strNGReults = tr("TBDIS_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.hxResult[0].TBtoHX_distance, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 4; // TBtoHX列
            break;
        case LT_Err:
            strNGReults = tr("LT_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.LT_SumArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 6; // LTsum列

            break;
        case HD_Err:
            strNGReults = tr("HD_Err");
            lines << QString("%1(%2)").arg(strNGReults).arg(result.HD_SumArea, 0, 'f', 2);
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 8; // HDsum列

            break;
        case NG:
            strNGReults = tr("NG");
            lines << strNGReults;
            styles.push_back(LineStyle{30, Qt::red, "Consolas"});
            errorColumn = 10; // 结果列

            break;
        default:
            break;
        }

        QImage pix = cvqt::drawImgText(result.dst, lines, styles,cv::Point(30,100));
        face.setDisplayImage(result.id,1,pix);

        QStringList headers = {};

        // 记录当前行索引
        int currentRowIndex = m_resultData[result.id].size();
        int displayIdx = (m_hxIndex[result.id] <= 8) ? m_hxIndex[result.id] : 25 - m_hxIndex[result.id];
        for (const auto& hx : result.hxResult)
        {
            m_resultData[result.id] << QVariant(QVariantList{
                QString::number(displayIdx),
                QString::number(hx.hx_weight, 'f', 2),
                QString::number(hx.hx_height, 'f', 2),
                QString::number(result.HX_Area,   'f', 2),
                QString::number(hx.TBtoHX_distance, 'f', 2),
                QString::number(hx.center_pianyi,   'f', 2),
                QString::number(result.LT_SumArea,   'f', 2),
                QString::number(result.LT_MaxArea,   'f', 2),
                QString::number(result.HD_SumArea,   'f', 2),
                QString::number(result.HD_MaxArea,   'f', 2),
                strNGReults
            });
            break;
        }
        if (m_resultData[result.id].size() == 1) {

            face.clearAllRowTextColors(result.id);
            face.clearAllCellTextColors(result.id);
        }
        face.setTableData(result.id, headers, m_resultData[result.id]);

        // 根据检测结果设置颜色
        if (result.NO_HX_NGReults != OK) {
            // 设置整行颜色为红色
            face.setRowTextColor(result.id, currentRowIndex, rowColor);

            // 设置导致错误的特定列颜色
            if (errorColumn >= 0) {
                face.setCellTextColor(result.id, currentRowIndex, errorColumn, specificColumnColor);
                face.setCellTextColor(result.id, currentRowIndex, 0, specificColumnColor);
                face.setCellTextColor(result.id, currentRowIndex, 10, specificColumnColor);
            }
        } else {
            // OK结果设置为绿色
            face.setRowTextColor(result.id, currentRowIndex, Qt::green);
        }

        m_hxIndex[result.id] ++;



        if (m_resultData[result.id].size() >= 8) {
            m_resultData[result.id].clear();
            m_hxIndex[result.id] = (result.id == 0) ? 1 : 9;
        }

        // 保存合成图像
        m_imageSaveManager->saveCompositeImage(cameraId, result.FusionMap, m_vTriggerIndexs[result.id]);

        WeldingResult weData;
        weData.NO_HX_NGReults = result.NO_HX_NGReults;
        weData.dst =  cvqt::qImageToCvMat(pix);
        // 保存检测结果图像
        m_imageSaveManager->saveResultImage(cameraId, weData, m_vTriggerIndexs[result.id]);

        // 重置原始图像索引，为下一次触发做准备
        m_vImgIndexs[result.id] = 1;
        m_vTriggerIndexs[result.id]++;

        if(cameraId ==1){
            m_ccd1_num++;
            if(result.NO_HX_NGReults != OK){
                m_ccd1_ng++;
            }
            if (m_ccd1_num > 0) {
                m_ccd1_rate = (float)(m_ccd1_num - m_ccd1_ng) / m_ccd1_num * 100.0f;
            } else {
                m_ccd1_rate = 0.0f; // 避免除以0
            }

        }

        if(cameraId ==2){
            m_ccd2_num++;
            if(result.NO_HX_NGReults != OK){
                m_ccd2_ng++;
            }
            if (m_ccd2_num > 0) {
                m_ccd2_rate = (float)(m_ccd2_num - m_ccd2_ng) / m_ccd2_num * 100.0f;
            } else {
                m_ccd2_rate = 0.0f; // 避免除以0
            }
        }
        QList<QPair<QString, QVariant>> okRateData = {
            {tr("CCD1:"), QString("%1%").arg(m_ccd1_rate, 0, 'f', 2)},
            {tr("CCD2:"), QString("%1%").arg(m_ccd2_rate, 0, 'f', 2)}
        };

        QList<QPair<QString, QVariant>> ngCountData = {
            {tr("CCD1:"), QString::number(m_ccd1_ng)},
            {tr("CCD2:"), QString::number(m_ccd2_ng)}
        };

        QList<QPair<QString, QVariant>> totalData = {
            {tr("CCD1:"), QString::number(m_ccd1_num)},
            {tr("CCD2:"), QString::number(m_ccd2_num)}
        };
        updateDynamicGroupBox(ui->gBox_ok, okRateData);
        updateDynamicGroupBox(ui->gBox_ng, ngCountData);
        updateDynamicGroupBox(ui->gBox_total, totalData);

        CFrameResult framData;
        framData.sig = 1;
        framData.camera = cameraId;
        framData.result = result.NO_HX_NGReults;
        emit sigFramResult(framData);

        // ========== 调用数据库存储函数 ==========
        if (!result.hxResult.empty()) {
            const auto& hx = result.hxResult[0]; // 取第一个焊锡结果

            DB_WeldingResult dbResult;
            dbResult.hxPort = (cameraId == 1)? "N端":"P端";                    // 相机端口
            dbResult.hxId = displayIdx;                       // 焊锡编号
            dbResult.hxBatch = 1;                          // 批次，没有的话记为1
            dbResult.hxWeight = hx.hx_weight;              // 焊锡长
            dbResult.hxHeight = hx.hx_height;              // 焊锡宽
            dbResult.hxArea = result.HX_Area;              // 焊锡面积
            dbResult.hxDistance = hx.TBtoHX_distance;      // 裸露铜引脚长度
            dbResult.hxPianyi = hx.center_pianyi;          // 焊锡偏移
            dbResult.hxLTSumArea = result.LT_SumArea;      // 漏铜总面积
            dbResult.hxLTMaxArea = result.LT_MaxArea;      // 漏铜最大面积
            dbResult.hxHDSumArea = result.HD_SumArea;      // 黑点总面积
            dbResult.hxHDMaxArea = result.HD_MaxArea;      // 黑点最大面积
            dbResult.hxReult = (result.NO_HX_NGReults == OK); // 检测结果
            dbResult.hxReultsDescribe = strNGReults; // 结果描述

            // 插入数据库
            if (!m_sql.insertWeldingResult(dbResult)) {
                qWarning() << "Failed to insert welding result into database for camera" << cameraId;
            } else {
                qDebug() << "Successfully inserted welding result into database for camera" << cameraId;
            }
        }
        // ========== 数据库存储结束 ==========
    }else{
        qDebug() << "CapSenseTriForm::onAlgorithmResultReady() sigCamResult";
        //本地测试
        emit sigCamResult(result);
    }
}

void CapSenseTriForm::onSysRuning(bool on)
{
    ui->Bt_start->setEnabled(on);
    // 如果系统开始运行且启用了自启动，并且当前不在运行状态，则自动启动
    if (on && SysEnv::instance().getAutoStart() && !m_isRun) {
        qDebug() << "Auto starting detection...";
        // 延迟一小段时间确保UI完全就绪
        QTimer::singleShot(500, this, [this]() {
            on_Bt_start_clicked();
        });
    }
}

void CapSenseTriForm::updateDataGroup(DataGroup group, const QList<QPair<QString, QVariant>> &data)
{
    switch(group) {
    case ConfigData:
        updateDynamicGroupBox(ui->gBox_config, data);
        break;
    case OkRateData:
        updateDynamicGroupBox(ui->gBox_ok, data);
        break;
    case NgCountData:
        updateDynamicGroupBox(ui->gBox_ng, data);
        break;
    case TotalData:
        updateDynamicGroupBox(ui->gBox_total, data);
        break;
    }
}

CapSenseForm *CapSenseTriForm::getDisplay(int index) const
{
    if(index >= 0 && index < displays.size()) {
        return displays[index];
    }
    return nullptr;
}

int CapSenseTriForm::getCameraID(const QString &cameraKey)
{
    static const QHash<QString,int> tbl = {
        {m_cameraKey1, 1},
        {m_cameraKey2, 2}
    };
    return tbl.value(cameraKey, 0);   // 找不到返回 0
}

inline QGraphicsDropShadowEffect *CapSenseTriForm::createShadow()
{
    QGraphicsDropShadowEffect* shadow = new QGraphicsDropShadowEffect(this);
    shadow->setOffset(0, 0);
    shadow->setColor(QColor(150, 150, 150));
    shadow->setBlurRadius(6);
    return shadow;
}

void CapSenseTriForm::updateDynamicGroupBox(QGroupBox *groupBox, const QList<QPair<QString, QVariant>> &data)
{
    QLayout* oldLayout = groupBox->layout();
    if (oldLayout) {
        QLayoutItem* item;
        while ((item = oldLayout->takeAt(0)) != nullptr) {
            delete item->widget();
            delete item;
        }
        delete oldLayout;
    }

    QFormLayout* layout = new QFormLayout(groupBox);
    layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
    layout->setContentsMargins(12, 15, 12, 12);
    layout->setSpacing(8);

    for (const auto &pair : data) {
        QLabel* valueLabel = new QLabel(pair.second.toString());
        valueLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
        valueLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

        QLabel* keyLabel = new QLabel(pair.first);
        keyLabel->setStyleSheet("font-weight: bold;");

        layout->addRow(keyLabel, valueLabel);
    }

    groupBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
}

void CapSenseTriForm::initCameras()
{
    //注册数据类型 不然信号槽会数据丢失
    qRegisterMetaType<CFrameInfo>("CFrameInfo");

    int ret = IMV_OK;
    // 连接相机之前不显示状态栏 | Don't show status bar before connecting camera

    ret = IMV_EnumDevices(&m_deviceInfoList, interfaceTypeAll);
    if (IMV_OK != ret)
    {
        printf("Enumeration devices failed! ErrorCode[%d]\n", ret);
        return;
    }
    if (m_deviceInfoList.nDevNum < 1)
    {
        ui->Bt_start->setEnabled(false);
    }
    else
    {
        createCameraThread(m_deviceInfoList);
    }
}

void CapSenseTriForm::createCameraThread(IMV_DeviceList m_deviceInfoList)
{
    for (unsigned int i = 0; i < m_deviceInfoList.nDevNum; i++)
    {
        QString cameraKey = m_deviceInfoList.pDevInfo[i].cameraKey;
        qDebug()<<"createCameraThread:" << cameraKey;
        QString cameraName = QString::fromLocal8Bit(m_deviceInfoList.pDevInfo[i].cameraName);
        QString ccdInfo;
        CameraThread* thread = new CameraThread(cameraKey);
        connect(thread, &CameraThread::sendAreaCamImage, this, &CapSenseTriForm::handleFrame);
        // connect(thread, &CameraThread::sendScanCamImage, this, &CapSenseTriForm::woodFrame);
        connect(thread, &CameraThread::errorOccurred, this, &CapSenseTriForm::handleError);

        cameraThreads.insert(cameraKey, thread);
        m_cameraThreadList.append(thread); // 添加到列表

        ccdInfo = QString("%1[%2]").arg(cameraKey).arg(cameraName);
        if (cameraKey == m_cameraKey1) {
            thread->m_worker->m_isAreaScan = true;
            thread->m_worker->m_nId = 1;
            SysEnv::instance().setModuleOk(SysEnv::CAM_A);
        } else if (cameraKey == m_cameraKey2) {
            thread->m_worker->m_isAreaScan = true;
            thread->m_worker->m_nId = 2;
            SysEnv::instance().setModuleOk(SysEnv::CAM_B);
        }
        thread->initialize();
    }
}

void CapSenseTriForm::releaseAllCameras()
{
    for (auto* thread : std::as_const(cameraThreads)) {
        thread->stop();
        delete thread;
    }
    cameraThreads.clear();
    m_cameraThreadList.clear(); // 清空列表
}

void CapSenseTriForm::upSaveImgPath(const QString &newPath)
{
    qDebug() << "Save path changed to:" << newPath;

    if (m_imageSaveManager) {
        m_imageSaveManager->updateSavePath(newPath);
    }
}

void CapSenseTriForm::updateRuntimeDisplay()
{
    qint64 hours = m_runtimeSeconds / 3600;
    qint64 minutes = (m_runtimeSeconds % 3600) / 60;
    qint64 seconds = m_runtimeSeconds % 60;

    m_runtimeString = QString("%1:%2:%3")
                          .arg(hours, 5, 10, QLatin1Char('0'))
                          .arg(minutes, 2, 10, QLatin1Char('0'))
                          .arg(seconds, 2, 10, QLatin1Char('0'));

    // 更新配置数据显示
    QList<QPair<QString, QVariant>> configData = {
        {"机械编号:", 1},
        {"运行时间:", m_runtimeString}
    };
    updateDynamicGroupBox(ui->gBox_config, configData);
}

void CapSenseTriForm::setSaveForm(SaveForm *saveForm)
{
    m_saveForm = saveForm;
    m_imageSaveManager->setSaveForm(m_saveForm);
}

void CapSenseTriForm::onAlgParamChanged(const InThresholdParam &param)
{
    m_currentAlgParam = param;
    Obj<WeldingDetector>::GetInstance()->InParam = param;
    QStringList headers;
    headers << tr("HXID")
            << tr("Weight(%1~%2mm)").arg(param.min_w).arg(param.max_w)
            << tr("Height(%1~%2mm)").arg(param.min_h).arg(param.max_h)
            << tr("Area(%1~%2mm²)").arg(param.min_area).arg(param.max_area)
            << tr("TBtoHX(%1~%2mm)").arg(param.min_TBDis).arg(param.max_TBDis)
            << tr("Offset(0~%1mm)").arg(param.max_PY)
            << tr("LTsum(0~%1mm²)").arg(param.LT_ALLArea_max)
            << tr("LTmax(0~%1mm²)").arg(param.LT_MAXArea_max)
            << tr("HDsum(0~%1mm²)").arg(param.HD_ALLArea_max)
            << tr("HDmax(0~%1mm²)").arg(param.HD_MAXArea_max)
            << tr("NO_HX_NGResults");

    QVariantList rowData;
    /* 旧数据不动，只更新表头 */
    CapSenseInterface face;
    face.setTableData(0, headers, rowData);
    face.setTableData(1, headers, rowData);
}

void CapSenseTriForm::onClearData()
{
    // 清除结果数据
    m_resultData[0].clear();
    m_resultData[1].clear();
    m_hxIndex = {1, 9};

    m_runtimeSeconds = 0;
    QList<QPair<QString, QVariant>> okRateData = {
        {tr("CCD1:"), "00.00%"},
        {tr("CCD2:"), "00.00%"}
    };
    QList<QPair<QString, QVariant>> ngCountData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    QList<QPair<QString, QVariant>> totalData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    m_ccd1_rate = 0;
    m_ccd1_ng = 0;
    m_ccd1_num = 0;

    m_ccd2_rate = 0;
    m_ccd2_ng = 0;
    m_ccd2_num = 0;

    updateDynamicGroupBox(ui->gBox_ok,     okRateData);
    updateDynamicGroupBox(ui->gBox_ng,     ngCountData);
    updateDynamicGroupBox(ui->gBox_total,  totalData);
}

void CapSenseTriForm::loadQssFile()
{
    QFile file(":/qss/CapSense.qss");
    if (file.open(QFile::ReadOnly))
    {
        QTextStream filetext(&file);
        QString stylesheet = filetext.readAll();
        this->setStyleSheet(stylesheet);
        file.close();
    }
}

void CapSenseTriForm::on_Bt_clear_clicked()
{
    QMessageBox::StandardButton btn =
        QMessageBox::question(this,
                              tr("info"),
                              tr("Are you sure you want to clear all statistics?"),
                              QMessageBox::Yes | QMessageBox::No,
                              QMessageBox::No);

    if (btn != QMessageBox::Yes)
        return;


    m_runtimeSeconds = 0;
    QList<QPair<QString, QVariant>> configData = {
        {"机械编号:", 1},
        {"运行时间:", "00000:00:00"}
    };
    QList<QPair<QString, QVariant>> okRateData = {
        {tr("CCD1:"), "00.00%"},
        {tr("CCD2:"), "00.00%"}
    };
    QList<QPair<QString, QVariant>> ngCountData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    QList<QPair<QString, QVariant>> totalData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    m_ccd1_rate = 0;
    m_ccd1_ng = 0;
    m_ccd1_num = 0;

    m_ccd2_rate = 0;
    m_ccd2_ng = 0;
    m_ccd2_num = 0;
    updateDynamicGroupBox(ui->gBox_config, configData);
    updateDynamicGroupBox(ui->gBox_ok,     okRateData);
    updateDynamicGroupBox(ui->gBox_ng,     ngCountData);
    updateDynamicGroupBox(ui->gBox_total,  totalData);




    // m_isRun = 1;
    // /* 随机数引擎 */
    // static std::mt19937 rng(std::random_device{}());
    // static std::uniform_int_distribution<int> dist(OK, NG);

    // auto makeFake = [](int camId)
    // {
    //     WeldingResult r;
    //     r.id = camId;
    //     r.NO_HX_NGReults = static_cast<DetectionRsult>(dist(rng)); // 随机枚举值
    //     r.FusionMap = cv::Mat(480, 640, CV_8UC3, cv::Scalar(255, 255, 0));
    //     r.dst       = r.FusionMap.clone();

    //     /* 随便填 2 条焊锡 */
    //     for (int i = 0; i < 1; ++i)
    //     {
    //         HXResult h;
    //         h.hxid = 1000 + camId * 10 + i;
    //         h.hx_weight   = 10.0f + i;
    //         h.hx_height   = 5.0f  + i;
    //         // h.hx_area     = 50.0f + i;
    //         h.TBtoHX_distance = 1.5f + i;
    //         h.center_pianyi   = 0.8f + i;
    //         r.hxResult.emplace_back(h);
    //     }
    //     return r;
    // };

    // onAlgorithmResultReady(makeFake(0));
    // onAlgorithmResultReady(makeFake(1));
}

void CapSenseTriForm::handleError(QString message)
{
    qDebug()<< message;
}

void CapSenseTriForm::initWindow()
{
    gridLayout_displays = new QGridLayout();
    gridLayout_displays->setSpacing(2);

    displays.clear();
    for (int i = 0; i < 2; ++i) {
        CapSenseForm* display = new CapSenseForm(this);
        display->setObjectName(QString("display_%1").arg(i + 1));
        displays.append(display);

        gridLayout_displays->addWidget(display, 0, i);
    }

    QWidget* leftContainer = new QWidget(this);
    leftContainer->setLayout(gridLayout_displays);

    QHBoxLayout* mainLayout = new QHBoxLayout(this);
    mainLayout->setContentsMargins(10, 10, 10, 10);
    mainLayout->setSpacing(2);
    mainLayout->addWidget(leftContainer, 5);
    mainLayout->addWidget(ui->display_sidebar, 1);

    QList<QPair<QString, QVariant>> configData = {
        {"机械编号:", 1},
        {"运行时间:", "00000:00:00"}
    };
    QList<QPair<QString, QVariant>> okRateData = {
        {tr("CCD1:"), "00.00%"},
        {tr("CCD2:"), "00.00%"}
    };
    QList<QPair<QString, QVariant>> ngCountData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    QList<QPair<QString, QVariant>> totalData = {
        {tr("CCD1:"), "00"},
        {tr("CCD2:"), "00"}
    };
    updateDynamicGroupBox(ui->gBox_config, configData);
    updateDynamicGroupBox(ui->gBox_ok, okRateData);
    updateDynamicGroupBox(ui->gBox_ng, ngCountData);
    updateDynamicGroupBox(ui->gBox_total, totalData);
    // 可选：设置自启动复选框样式
    ui->cb_autoStart->setStyleSheet(
        "QCheckBox {"
        "    spacing: 5px;"
        "    font-weight: bold;"
        "}"
        "QCheckBox::indicator {"
        "    width: 16px;"
        "    height: 16px;"
        "}"
        );
}

void CapSenseTriForm::on_Bt_start_clicked()
{
    enableLocalMode = false;
    if(m_isRun){
        ui->Bt_start->setText(tr("start"));
        m_runtimeTimer->stop();
        for (CameraThread* thread : m_cameraThreadList) {
            thread->stop();
        }
    } else {
        ui->Bt_start->setText(tr("stop"));
        m_runtimeTimer->start(1000);
        for (CameraThread* thread : m_cameraThreadList) {
            thread->start();
        }
    }
    m_isRun = 1 - m_isRun;
}

void CapSenseTriForm::readConfig()
{
    QString Path = "configs/configs.ini";
    QSettings iniRead(Path, QSettings::IniFormat);
    iniRead.setIniCodec(QTextCodec::codecForName("UTF_8"));

    // 相机1~2的key
    m_cameraKey1 = iniRead.value("CameraKey/cameraKey1").toString();
    m_cameraKey2 = iniRead.value("CameraKey/cameraKey2").toString();

}

void CapSenseTriForm::on_cb_autoStart_clicked(bool checked)
{
    // 保存设置到 SysEnv
    SysEnv::instance().setAutoStart(checked);
    qDebug() << "Auto start setting changed to:" << checked;
}

